package com.ddogring.web.controller.alipay;

import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConstants;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ddogring.alipay.config.AliPayConfig;
import com.ddogring.business.domain.Order;
import com.ddogring.business.domain.UnifiedPay;
import com.ddogring.business.service.IAliPayService;
import com.ddogring.business.service.IOrderService;
import com.ddogring.business.service.IUnifiedPayService;
import com.ddogring.common.constant.Constants;
import com.ddogring.common.core.controller.BaseController;
import com.ddogring.common.core.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;


/**
 * @BelongsProject: eshop
 * @BelongsPackage: com.ddogring.web.controller.alipay
 * @Author: DdogRing
 * @CreateTime: 2023-02-01  11:52
 * @Description: TODO
 * @Version: 1.0
 */
@Controller
public class AliPayController extends BaseController {

    @Autowired
    private IAliPayService aliPayService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IUnifiedPayService unifiedPayService;

    /**
     * @description: 付款接口
     * @author: DdogRing
     * @date: 2023/2/2 13:49
     * @param: [map, model]
     * @return: java.lang.String
     **/
    @PostMapping("/api/toAlipayRecharge")
    @ResponseBody
    public AjaxResult toAlipayRecharge(@RequestBody Map<String, Object> map, Model model) {

        if (null == map) {
            return AjaxResult.error();
        }

        String result = "";
        try {
            map.put("userId", getLoginUser().getUserId());
            result = aliPayService.aliPay(map);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
        System.out.println(result);
        return AjaxResult.success(result);
    }

    /**
     * @description: 测试接口
     * @author: DdogRing
     * @date: 2023/2/2 13:49
     * @param: [out_trade_no, total_amount, subject, model]
     * @return: java.lang.String
     * TODO
     **/
    @GetMapping("/loan/toAlipay")
    public String toAlipayRecharge(@RequestParam("out_trade_no") String out_trade_no,
                                    @RequestParam("total_amount") String total_amount,
                                    @RequestParam("subject") String subject,
                                   Model model) throws AlipayApiException {

        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.gatewayUrl, AliPayConfig.app_id, AliPayConfig.merchant_private_key, "json", AliPayConfig.charset, AliPayConfig.alipay_public_key, AliPayConfig.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();

        alipayRequest.setNotifyUrl(AliPayConfig.notify_url);
        alipayRequest.setReturnUrl(AliPayConfig.return_url);

        JSONObject bizContent = new JSONObject();
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        bizContent.put("out_trade_no", out_trade_no);
        bizContent.put("total_amount", total_amount);
        bizContent.put("subject", subject);
        alipayRequest.setBizContent(bizContent.toString());

        System.out.println(bizContent);


        // 请求支付宝
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        System.out.println(result);
        model.addAttribute("result", result);

        QueryWrapper<UnifiedPay> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("unified_pay", out_trade_no);
        List<UnifiedPay> unifiedPays = unifiedPayService.list(queryWrapper);
        if(null != unifiedPays && unifiedPays.size() > 0) {
            for (UnifiedPay unifiedPay:unifiedPays) {
                String orderId = unifiedPay.getOrderId();
                UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("order_id", orderId);
                updateWrapper.set("status", 1);
                orderService.update(updateWrapper);
            }
        }
        return "payToAlipay";
    }

    /**
     * 支付宝验证订单
     * @param out_trade_no
     * @return
     * @throws AlipayApiException
     * @throws UnsupportedEncodingException
     */
    @GetMapping("/loan/aliPayQueryOrder")
    @ResponseBody
    public String aliPayQueryOrder(@RequestParam(name="out_trade_no",required = true) String out_trade_no) throws AlipayApiException, UnsupportedEncodingException {

        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.gatewayUrl, AliPayConfig.app_id, AliPayConfig.merchant_private_key, "json", AliPayConfig.charset, AliPayConfig.alipay_public_key, AliPayConfig.sign_type);

        //设置请求参数
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\"}");

        //请求
        return alipayClient.execute(alipayRequest).getBody();
    }

    @PostMapping("/loan/back")
    @ResponseBody
    public String back(@RequestParam Map<String, String> params) throws AlipayApiException {

        System.out.println("========支付通知=========");

        System.out.println("params======>" + params);

        //异步通知验签
        boolean signVerified = AlipaySignature.rsaCheckV1(
                params,
                AliPayConfig.alipay_public_key,
                AliPayConfig.charset,
                AliPayConfig.sign_type); //调用SDK验证签名

        if(!signVerified) {
            //验签失败则记录异常日志，并在response中返回failure.
            System.out.println("支付成功异步验签失败");
            return "支付成功异步验签失败";
        }

        //1.商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号
        String outTradeNo = params.get("out_trade_no");
        QueryWrapper<UnifiedPay> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("unified_pay", outTradeNo);
        List<UnifiedPay> unifiedPays = unifiedPayService.list(queryWrapper);
        if(unifiedPays == null || unifiedPays.size() == 0){
            System.out.println("订单不存在");
            return "订单不存在";
        }

        BigDecimal total_amount = BigDecimal.ZERO;
        for (UnifiedPay unifiedPay:unifiedPays) {
            BigDecimal payNum = unifiedPay.getPayNum();
            total_amount = total_amount.add(payNum);
        }

        //2.判断 total_amount 是否确实为该订单的实际金额（即商户订单创建时的金额）
        String totalAmount = params.get("total_amount");
        BigDecimal bigDecimal = new BigDecimal(totalAmount);
        if(!total_amount.equals(bigDecimal)){
            System.out.println("金额校验失败");
            return "金额校验失败";
        }

        //在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS支付宝才会认定为买家付款成功。
        String tradeStatus = params.get("trade_status");
        if(!"TRADE_SUCCESS".equals(tradeStatus)){
            System.out.println("支付未成功");
            return "支付未成功";
        }

        // 订单状态修改
        for (UnifiedPay unifiedPay:unifiedPays) {
            String orderId = unifiedPay.getOrderId();
            UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("order_id", orderId);
            updateWrapper.set("status", 1);
            orderService.update(updateWrapper);
        }

        //校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
        //向支付宝反馈，否则会不断发送通知（25小时内8次）,对此我们处理重复通知
        return "success";
    }
}
